local BANK_OPCODE = 122 

local bankWindow = nil
local bankToggleButton = nil
local jsonBuffer = "" 

local invBal = 0
local bankBal = 0

local canClick = true


function init()
    connect(g_game, {
        onGameStart = create,
        onGameEnd = destroy
    })

    ProtocolGame.registerExtendedOpcode(BANK_OPCODE, onExtendedOpcode)

    if g_game.isOnline() then
        create()
    end
end

function terminate()
    disconnect(g_game, {
        onGameStart = create,
        onGameEnd = destroy
    })
    ProtocolGame.unregisterExtendedOpcode(BANK_OPCODE)
    destroy()
end

function create()
    if bankWindow then return end

    bankToggleButton = modules.client_topmenu.addRightGameToggleButton("bankButton", tr("Bank"), "/images/topbuttons/bank", toggleBankWindow, true)
    
    bankWindow = g_ui.displayUI('bank')
    bankWindow:hide()

    local inventoryBalanceText = bankWindow:recursiveGetChildById('inventoryBalanceText')
	local bankBalanceText = bankWindow:recursiveGetChildById('bankBalanceText')


	local depositButton = bankWindow:recursiveGetChildById("depositButton")
	depositButton.onClick = function()
		createDepositWindow("Deposit")
	end
	
	local drawall = bankWindow:recursiveGetChildById('withdrawAllButton')
	local depositAll = bankWindow:recursiveGetChildById('depositAllButton')
	depositAll.onClick = function()
		if invBal <= 0 then
			return
		end
		if not canClick then return end
		blockClicksFor(1.5, {drawall, depositAll})
	  
		sendBankRequest("depositAll", invBal)
	end
	
	drawall.onClick = function()
		if bankBal <= 0 then
			return
		end
		if not canClick then return end
		blockClicksFor(1.5, {drawall, depositAll})
	  
		sendBankRequest("withdrawAll", bankBal)
	end

	local withdrawButton = bankWindow:recursiveGetChildById("withdrawButton")
	withdrawButton.onClick = function()
		createDepositWindow("Withdraw")
	end	

	bankWindow.onClose = function()
        if bankToggleButton then
            bankToggleButton:setOn(false)
        end
    end

end

function createDepositWindow(title, maxMoney)
    local root = g_ui.getRootWidget()
    local old = root:recursiveGetChildById("depositWindow")
    if old then old:destroy() end

    local window = g_ui.loadUI('depositwindow', g_ui.getRootWidget())
    if not window then
        return
    end
	
	if((string.find(title, "Withdraw") ~= nil) and bankBal <= 0) then
		displayErrorBox("Withdraw error!", "Você não tem money no bank!")
		window:destroy()
		return
	elseif((string.find(title, "Deposit") ~= nil) and invBal <= 0) then
		displayErrorBox("Deposit error!", "Você não tem money na bag!")
		window:destroy()
		return
	end
	
	window:setText("Bank "..title)
	window:recursiveGetChildById('titleLabel'):setText(title.." Money")	
	
	local maxMoneyLabel = window:recursiveGetChildById('maxMoney')
	if maxMoneyLabel then
	  local show = (string.find(title, "Withdraw") ~= nil) and bankBal or invBal
	  maxMoneyLabel:setText("Total: $"..formatNumber(show))
	  maxMoneyLabel:setColor("green")
	end

    local input = window:recursiveGetChildById('depositAmountInput')
	input:focus()
    local okButton = window:recursiveGetChildById('okButton')
    local cancelButton = window:recursiveGetChildById('cancelButton')
	
	window.onKeyPress = function(self, keyCode, keyboardModifiers)
	  if keyCode == KeyEnter or keyCode == KeyReturn then
		okButton:onClick()
		return true
	  elseif keyCode == KeyEscape then
		cancelButton:onClick()
		return true
	  end
	  return false
	end

    okButton.onClick = function()
        local value = tonumber(input:getText())
        if value and value > 0 then
            sendBankRequest(string.lower(title), value)
            window:destroy()
        else
            displayErrorBox("Invalid amount", "Please enter a valid number greater than zero.")
        end
    end

    cancelButton.onClick = function()
        window:destroy()
    end
end


function destroy()
    if bankToggleButton then
        bankToggleButton:destroy()
        bankToggleButton = nil
    end
    if bankWindow then
        bankWindow:destroy()
        bankWindow = nil
    end
    jsonBuffer = ""
end

function toggleBankWindow()
    if not bankWindow then
        create() 
    end

    if bankWindow:isVisible() then
        hideBankWindow()
    else
        showBankWindow()
    end
end

function showBankWindow()
    if not bankWindow then return end
    bankWindow:show()
    bankWindow:raise()
    bankWindow:focus()
    if bankToggleButton then bankToggleButton:setOn(true) end
    sendBankRequest("requestBalance")
end

function hideBankWindow()
    if not bankWindow then return end
    bankWindow:hide()
    if bankToggleButton then bankToggleButton:setOn(false) end
end

function onExtendedOpcode(protocol, code, buffer)
    if code ~= BANK_OPCODE then return end

    local char = buffer:sub(1, 1)
    local endData = false
    if char == "E" then endData = true end

    local partialData = false
    if char == "S" or char == "P" or char == "E" then
        partialData = true
        buffer = buffer:sub(2)
        jsonBuffer = jsonBuffer .. buffer
    end

    if partialData and not endData then
        return
    end
    
    local json_status, json_data = pcall(function()
        return json.decode(endData and jsonBuffer or buffer)
    end)

    jsonBuffer = ""
    if not json_status then
        return
    end

    local action = json_data.action
    local data = json_data.data

    if action == "updateBalance" then
        updateBalancesUI(data)
    end
end

function updateBalancesUI(data)
    local inventoryBalanceText = bankWindow:recursiveGetChildById('inventoryBalanceText')
    local bankBalanceText = bankWindow:recursiveGetChildById('bankBalanceText')
    if not inventoryBalanceText or not bankBalanceText then return end

	invBal = tonumber(data.inventory) or 0
	bankBal = tonumber(data.bank) or 0

    inventoryBalanceText:setText("$" .. formatNumber(invBal))
    bankBalanceText:setText("$" .. formatNumber(bankBal))
end

function sendBankRequest(actionType, value)
    local requestData = { action = actionType }
    if value ~= nil then requestData.value = value end
    local jsonString = json.encode(requestData)
    g_game.getProtocolGame():sendExtendedOpcode(BANK_OPCODE, jsonString)
end

function formatNumber(value)
    local formatted = tostring(value)
    local k
    while true do
        formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1.%2')
        if k == 0 then
            break
        end
    end
    return formatted
end

function blockClicksFor(seconds, buttons)
  canClick = false
  for _, btn in pairs(buttons) do
    btn:setEnabled(false)
  end

  scheduleEvent(function()
    canClick = true
    for _, btn in pairs(buttons) do
      btn:setEnabled(true)
    end
  end, seconds * 1000)
end



modules.game_bank = {
    toggleBankWindow = toggleBankWindow,
    showBankWindow = showBankWindow,
    hideBankWindow = hideBankWindow,
    updateBalancesUI = updateBalancesUI,
    sendBankRequest = sendBankRequest,
    version = "1.0"
}